package tomasulogui;

public class BranchUnit
        extends FunctionalUnit {

    public static final int EXEC_CYCLES = 1;

    public BranchUnit(PipelineSimulator sim) {
        super(sim);
    }

    public int calculateResult(int station) {
        ReservationStation stat = stations[station];
        stat.addressValid = true;
        boolean branch = false;
        switch(stat.getFunction()){
            case BEQ:
                if(stat.getData1() == stat.getData2()){
                    branch = true;
                    stat.address = stat.immediate + stat.pc + 4;
                }
                break;
            case BNE:
                if(stat.getData1() != stat.getData2()){
                    branch = true;
                    stat.address = stat.immediate + stat.pc + 4;
                }
                break;
            case BLTZ:
                if(stat.getData1() < 0){
                    branch = true;
                    stat.address = stat.immediate + stat.pc + 4;
                }
                break;
            case BLEZ:
                if(stat.getData1() <= 0){
                    branch = true;
                    stat.address = stat.immediate + stat.pc + 4;
                }
                break;
            case BGTZ:
                if(stat.getData1() > 0){
                    branch = true;
                    stat.address = stat.immediate + stat.pc + 4;
                }
                break;
            case BGEZ:
                if(stat.getData1() >= 0){
                    branch = true;
                    stat.address = stat.immediate + stat.pc + 4;
                }
                break;
            case J:
                branch = true;
                stat.address = stat.immediate + stat.pc + 4;
                break;
            case JAL:
                branch = true;
                stat.address = stat.immediate + stat.pc + 4;
                break;
            case JR:
                branch = true;
                stat.address = stat.getData1();
                break;
            case JALR:
                branch = true;
                stat.address = stat.getData1();
                break;
            default:
                stat.addressValid = false;
        }
        
        
        simulator.getROB().getEntryByTag(stat.destTag).setBranchTaken(branch);
        if(branch){
            simulator.getROB().getEntryByTag(stat.destTag).setBranchTgt(stat.address);
        }
        else{
            simulator.getROB().getEntryByTag(stat.destTag).setBranchTgt(stat.pc + 4);
        }
        
        simulator.getBTB().setBranchAddress(stat.pc, stat.address);
        simulator.getBTB().setBranchResult(stat.pc, branch);
        
        return stat.pc + 4;
    }

    public int getExecCycles() {
        return EXEC_CYCLES;
    }
}
